package com.yxh.lib_base.ext.viewbinding

import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
import com.yxh.lib_base.ext.viewbinding.ext.addObserverDestroyed
import com.yxh.lib_base.ext.viewbinding.ext.bindMethod
import com.yxh.lib_base.ext.viewbinding.ext.inflateMethod
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty


inline fun <reified T : ViewBinding> Fragment.binding() =
    FragmentBindingDelegate(T::class.java, this,false)

/**
 *  Fragment 中使用
 * 使用：val mBinding by viewBinding<xxxBinding>()
 * */
inline fun <reified T : ViewBinding> Fragment.viewBinding() =
    FragmentBindingDelegate(T::class.java, this,false)


class FragmentBindingDelegate<T : ViewBinding>(
    classes: Class<T>,
    val fragment: Fragment,
    val bind: Boolean = true
) : ReadOnlyProperty<Fragment, T> {

    var viewBinding: T? = null
    val bindMethod = classes.bindMethod()
    val inflateMethod = classes.inflateMethod()

    init {
        fragment.lifecycle.addObserverDestroyed { destroyed() }
    }

    override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
        return viewBinding?.run {
            return this
        } ?: let {
            val bind = when (bind) {
                true -> bindMethod.invoke(null, thisRef.view) as T
                else -> inflateMethod.invoke(null, thisRef.layoutInflater) as T
            }
            if (bind is ViewDataBinding){
                bind.lifecycleOwner =fragment
            }
            return bind.apply { viewBinding = this }
        }
    }

    private fun destroyed() {
        viewBinding = null
    }
}
